﻿#ifndef __SS_HASH_H__
#define __SS_HASH_H__
#include <stddef.h>
#include "../ssBaseDefine.h"

namespace StarSeeker
{
//整数哈希
inline u32 Hash32(u32 key)
{
	key = ~key + (key << 15); // key = (key << 15) - key - 1;
	key = key ^ (key >> 12);
	key = key + (key << 2);
	key = key ^ (key >> 4);
	key = key * 2057; // key = (key + (key << 3)) + (key << 11);
	key = key ^ (key >> 16);
	return key;
}

inline u64 Hash64(u64 key)
{
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

inline u32 Hash64To32(u64 key)
{
	key = (~key) + (key << 18); // key = (key << 18) - key - 1;
	key = key ^ (key >> 31);
	key = key * 21; // key = (key + (key << 2)) + (key << 4);
	key = key ^ (key >> 11);
	key = key + (key << 6);
	key = key ^ (key >> 22);
	return (u32)key;
}

// DJB Hash 
template<typename T>
inline ulint DJBHashCode(const T* str, ulint length)
{
	ulint hashcode = 5381;

	for (ulint i = 0; i < length; ++i)
	{
		hashcode = ((hashcode << 5) + hashcode) + str[i];
	}
	return hashcode;
}
// BKDR Hash 
template <typename T>
inline ulint BKDRHashCode(const T* str, ulint length)
{
	ulint seed = 131; // 31 131 1313 13131 131313 etc..
	ulint hash = 0;

	for (size_t i = 0; i < length; ++i)
	{
		hash = hash*seed + str[i];
	}

	return (hash & 0x7FFFFFFF);
}
// nginx用的hash
inline ulint MurmurHashCode(const u8* str, ulint length)
{
	ulint h = 0 ^ length;
	u32 k = 0;
	while (length >= 4)
	{
		k = str[0];
		k |= str[1] << 8;
		k |= str[2] << 16;
		k |= str[3] << 24;

		k *= 0x5bd1e995;
		k ^= k >> 24;
		k *= 0x5bd1e995;

		h *= 0x5bd1e995;
		h ^= k;

		str += 4;
		length -= 4;
	}

	switch (length)
	{
	case 3:
		h ^= str[2] << 16;
	case 2:
		h ^= str[1] << 8;
	case 1:
		h ^= str[0];
		h *= 0x5bd1e995;
	}
	h ^= h >> 13;
	h *= 0x5bd1e995;
	h ^= h >> 15;

	return h;
}

}
#endif
